﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace PrototypeGA
{
    public partial class Form1 : Form
    {
        Bitmap bm;
        Bitmap bm2;
        String str;
        String str2;
        String str3;
        Vector[] map;
        Pen[] pens;

        public Form1()
        {
            bm = new Bitmap(1100, 1100);
            for (int i = 0; i < 1100; i++)
            {
                for (int j = 0; j < 1100; j++)
                {

                    bm.SetPixel(i, j, Color.White);
                }
            }
            bm2 = new Bitmap(1100, 200);
            for (int i = 0; i < 1100; i++)
            {
                for (int j = 0; j < 200; j++)
                {

                    bm2.SetPixel(i, j, Color.SlateGray);
                }
            }
            map = new Vector[12];
            int numBus = 2;
            int maxStop = 12;
            map[0] = new Vector(5, 0,10,10);
            map[1] = new Vector(5, 1,20,10);
            map[2] = new Vector(5, 2,30,10);
            map[3] = new Vector(5, 3,10,20);
            map[4] = new Vector(5, 4,20,20);
            map[5] = new Vector(5, 5, 30, 20);
            map[6] = new Vector(5, 6, 10, 30);
            map[7] = new Vector(5, 7, 20, 30);
            map[8] = new Vector(5, 8, 30, 30);
            map[9] = new Vector(5, 9, 10, 40);
            map[10] = new Vector(5, 10, 20, 40);
            map[11] = new Vector(5, 11, 30, 40);
            
            //paint vectors
            Graphics canvas = Graphics.FromImage(bm);
            Brush myBrush = new System.Drawing.SolidBrush(Color.Black);
            for (int i = 0; i < maxStop; i++)
            {
                canvas.FillEllipse(myBrush, map[i].x*5, map[i].y*5, 10, 10);
            }
            //MUST SET SHORTEST DISTANCE ARRAY
            double[,] initialDist = new double[12, 12]{{0,10,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue},
                                                       {10,0,Double.MaxValue,Double.MaxValue,10,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue},
                                                       {Double.MaxValue,Double.MaxValue,0,Double.MaxValue,Double.MaxValue,10,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue},
                                                       {Double.MaxValue,Double.MaxValue,Double.MaxValue,0,10,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue},
                                                       {Double.MaxValue,10,Double.MaxValue,10,0,10,Double.MaxValue,10,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue},
                                                       {Double.MaxValue,Double.MaxValue,10,Double.MaxValue,10,0,Double.MaxValue,Double.MaxValue,10,Double.MaxValue,Double.MaxValue,Double.MaxValue},
                                                       {Double.MaxValue,Double.MaxValue,Double.MaxValue,10,Double.MaxValue,Double.MaxValue,0,10,Double.MaxValue,10,Double.MaxValue,Double.MaxValue},
                                                       {Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,10,Double.MaxValue,10,0,Double.MaxValue,Double.MaxValue,10,Double.MaxValue},
                                                       {Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,10,Double.MaxValue,10,0,Double.MaxValue,Double.MaxValue,10},
                                                       {Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,10,Double.MaxValue,Double.MaxValue,0,Double.MaxValue,Double.MaxValue},
                                                       {Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,10,Double.MaxValue,Double.MaxValue,0,Double.MaxValue},
                                                       {Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,Double.MaxValue,10,Double.MaxValue,Double.MaxValue,0}};

            //paint edges
            Brush myBrushG = new System.Drawing.SolidBrush(Color.Yellow);
            Pen myPen = new System.Drawing.Pen(myBrushG);
            for (int i = 0; i < maxStop; i++)
            {
                for (int j = 0; j < maxStop; j++)
                {
                    if (initialDist[i, j] < Double.MaxValue)
                    {
                       canvas.DrawLine(myPen, map[i].x * 5, map[i].y * 5, map[j].x * 5, map[j].y * 5);
                    }
                }
            }
            Warshal shortestDistanceCalculator = new Warshal(initialDist, maxStop);
            shortestDistanceCalculator.calcShortestDistArray();
            double[,] shrt = shortestDistanceCalculator.getShortestDistances();

            

            Genetics testRun = new Genetics(100, numBus, maxStop, maxStop);
            testRun.setMap(map);
            testRun.initializeGeneArray();
            testRun.setShortestDistanceArray(shrt);
            int[] fitnesses = new int[100];
            int drawIndex = 0;
            int willDraw = 0;
            for (int i = 0; i < 10000; i++)
            {
                testRun.mutatePopulation();
                fitnesses = testRun.testFitnessAll();
                testRun.repopulatePool(fitnesses);
                double averageFitness = 0;
                double maxFitness = Double.MinValue;
                for (int u = 0; u < fitnesses.Length; u++)
                {
                    averageFitness += fitnesses[u];
                    if (fitnesses[u] > maxFitness)
                    {
                        maxFitness = fitnesses[u];
                    }

                }
                averageFitness = averageFitness / fitnesses.Length;
                if ((willDraw % 10) == 0)
                {
                    bm2.SetPixel((int)drawIndex, (int)averageFitness * 10, Color.Black);
                    bm2.SetPixel((int)drawIndex, (int)maxFitness * 10, Color.Green);
                    willDraw++;
                    drawIndex++;
                }
                else
                {
                    willDraw++;
                }
                    
                


            }

            fitnesses = testRun.testFitnessAll();

            int destInd = -1;
            double best = 0;
            for (int i = 0; i < 100; i++)
            {
                if (fitnesses[i] > best)
                {
                    best = fitnesses[i];
                    destInd = i;
                }
            }

            Vector[,,] pool = testRun.getGenePool();
            Vector[,] solution = new Vector[numBus, maxStop];
            for (int i = 0; i < numBus; i++)
            {
                for (int j = 0; j < maxStop; j++)
                {
                    solution[i, j] = pool[destInd, i, j];
                }
            }

            PrototypeGA.Genetics.Bus[] busSolution = testRun.getBusArray(destInd);

            pens = new Pen[numBus];
            pens[0] = new Pen(Color.Red);
            pens[1] = new Pen(Color.Blue);
            //pens[2] = new Pen(Color.ForestGreen);
            //pens[3] = new Pen(Color.Orange);
            //pens[4] = new Pen(Color.Green);

            for (int i = 0; i < numBus; i++)
            {
                for (int j = 0; j < maxStop-1; j++)
                {
                    //canvas.DrawLine(pens[1], solution[i, j].x*5 + i, solution[i, j].y*5 + i, solution[i, j + 1].x*5 + i, solution[i, j + 1].y*5 + i);
                }
            }

            //initialize forms
            InitializeComponent();

            str = "" + solution[0, 0].id;
            str2 = "" + solution[1, 0].id;
            //str3 = "" + solution[2, 0].id; 

            for (int i = 0; i < 11; i++)
            {
                str += shortestDistanceCalculator.getPath(solution[0, i].id, solution[0, i + 1].id);
                //str = str + " " + solution[0, i+1].id + " ";
                str2 += shortestDistanceCalculator.getPath(solution[1, i].id, solution[1, i + 1].id);
                //str2 = str2 + " " + solution[1, i+1].id + " ";
                //str3 += shortestDistanceCalculator.getPath(solution[2, i].id, solution[2, i + 1].id);
            }

            textBox1.Text = str;
            textBox2.Text = str2;
            textBox3.Text = busSolution[0].passengers.ToString();
            textBox4.Text = busSolution[1].passengers.ToString();


          
            
            /*String str3 = " " + solution[2, 0].id;
            str3 += shortestDistanceCalculator.getPath(solution[2, 0].id, solution[2, 1].id);
            str3 = str3 + " " + solution[2, 1].id + " ";
            str3 += shortestDistanceCalculator.getPath(solution[2, 1].id, solution[2, 2].id);
            str3 = str3 + " " + solution[2, 2].id + " ";
            str3 += shortestDistanceCalculator.getPath(solution[2, 2].id, solution[2, 3].id);
            str3 = str3 + " " + solution[2, 3].id + " ";
            str3 += shortestDistanceCalculator.getPath(solution[2, 3].id, solution[2, 4].id);
            str3 = str3 + " " + solution[2, 4].id + " ";
            str3 += shortestDistanceCalculator.getPath(solution[2, 4].id, solution[2, 5].id);
            str3 = str3 + " " + solution[2, 5].id + " ";
            str3 += shortestDistanceCalculator.getPath(solution[2, 5].id, solution[2, 6].id);
            str3 = str3 + " " + solution[2, 6].id + " ";
            str3 += shortestDistanceCalculator.getPath(solution[2, 6].id, solution[2, 7].id);
            str3 = str3 + " " + solution[2, 7].id + " ";
            str3 += shortestDistanceCalculator.getPath(solution[2, 7].id, solution[2, 8].id);
            str3 = str3 + " " + solution[2, 8].id + " ";



            char[] test3 = str3.ToCharArray();
            int currentId3 = 0;



            for (int i = 1; i < test3.Length; i++)
            {


                if (test3[i] == ' ')
                {
                }

                else
                {
                    int next3 = Int32.Parse(Char.ToString(test3[i]));
                    canvas.DrawLine(pens[2], map[currentId3].x * 5+3, map[currentId3].y * 5+3, map[next3].x * 5, map[next3].y * 5+3);
                    currentId3 = next3;
                }
            }*/
            

        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics graphicsObj = e.Graphics;

            graphicsObj.DrawImage(bm, 0, 0, bm.Width, bm.Height);
            graphicsObj.DrawImage(bm2, 300, 25, bm2.Width, bm2.Height);

            graphicsObj.Dispose();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Graphics canvas = Graphics.FromImage(bm);
            string[] test = str.Split(' ');
            int currentId = 0;
            for (int i = 0; i < test.Length; i++)
            {
                if (test[i].Equals(""))
                {
                }

                else
                {
                    int next = Int32.Parse(test[i]);
                    canvas.DrawLine(pens[0], map[currentId].x * 5 + 2, map[currentId].y * 5 + 2, map[next].x * 5 + 2, map[next].y * 5+ 2);
                    currentId = next;
                }
            }
            this.Refresh();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Graphics canvas = Graphics.FromImage(bm);
            string[] test2 = str2.Split(' ');
            int currentId2 = 0;
            for (int i = 0; i < test2.Length; i++)
            {
                if (test2[i].Equals(""))
                {
                }

                else
                {
                    int next = Int32.Parse(test2[i]);
                    canvas.DrawLine(pens[1], map[currentId2].x * 5, map[currentId2].y * 5, map[next].x * 5, map[next].y * 5);
                    currentId2 = next;
                }
            }
            this.Refresh();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            Graphics canvas = Graphics.FromImage(bm);

            string[] test3 = str3.Split(' ');
            int currentId3 = 0;
            for (int i = 0; i < test3.Length; i++)
            {
                if (test3[i].Equals(""))
                {
                }

                else
                {
                    int next = Int32.Parse(test3[i]);
                    canvas.DrawLine(pens[2], map[currentId3].x * 5 + 3, map[currentId3].y * 5+3, map[next].x * 5, map[next].y * 5);
                    currentId3 = next;
                }
            }
            this.Refresh();

        }

        
        
    }
}
